#include "Main_FilesOS.h"
char *Save_File_Name = "FileOs_Save";

int Start_File_System(int model) //打开文件系统
{
  /*
    若存在文件系统
      则检验文件信息，检查文件首是否为魔数
      若是:将文件加载进内存区域
      若否:创建新文件
    若不存在文件系统
      则创建新文件
    */
  myvhard = (unsigned char *)malloc(OS_Size); //申请内存空间
  FILE *file;
  if ((file = fopen(Save_File_Name, "r")) != NULL) //已经存在文件系统
  {
    fread(buffer, OS_Size, 1, file);
    fclose(file);
    if (model == 1)
    {
      printf("The File_System has been established,Please open it!\n");
      return -1;
    }
    if (memcmp(buffer, "10101010", 8) == 0) //已经存在的文件是合法的文件系统
    {
      memcpy(myvhard, buffer, OS_Size);
      printf("Sucessfully open the exist File_System!\n");
    }
    else
    {
      printf("Error File_System!\n");
    }
  }
  else //不存在文件系统
  {
    if (model == 2)
    {
      printf("The File_System hasn't been established yet,Please create it!\n");
      return -1;
    }

    printf("Establishing File_System!\n");
    printf("Formating the File_System!\n");
    Format(Save_File_Name);
    memcpy(buffer, myvhard, OS_Size);
  }

  fcb *root;                                        //定义文件系统根目录
  root = (fcb *)(myvhard + 5 * BlockSize);          //为启动区空出五个数据块位置
  strcpy(opfilelist[0].File_Name, root->File_Name); //文件名
  strcpy(opfilelist[0].EX_Name, root->EX_Name);     //文件扩展名
  opfilelist[0].Attribute = root->Attribute;        //文件属性
  opfilelist[0].time = root->time;
  opfilelist[0].date = root->date;
  opfilelist[0].First_Block = root->First_Block;
  opfilelist[0].Length = root->Length;
  opfilelist[0].Is_Free = root->Is_Free;

  opfilelist[0].Dir_Num = 5; //文件目录的其实盘块号为五
  opfilelist[0].Diroff = 0;
  strcpy(opfilelist[0].Dir, "/root/");
  opfilelist[0].Cont = 0;
  opfilelist[0].FcbState = 0;
  opfilelist[0].TopenFile = 1;

  startp = ((block0 *)myvhard)->Start_Block;
  currfd = 0;
  return 0;
}

void Exit_File_System() //关闭文件系统，并将内存中信息写入文件
{
  /*
    若存在打开文件
      则依次关闭
    否则
      将内存空间信息写入Save_File_Name
    */
  while (currfd)
  {
    Close(currfd);
  }
  //  printf("%s", Save_File_Name);
  FILE *fp = fopen(Save_File_Name, "w");
  fwrite(myvhard, OS_Size, 1, fp);
  fclose(fp);
}

void Format(char *filename) //初始化内存磁盘空间
{
  /*
  初始化前五个磁盘块
  设定磁盘块六号为文件系统根目录磁盘块
  初始化root根目录：创建.和..目录
  写入Save_File_Name文件到磁盘空间
  */
  block0 *boot = (block0 *)myvhard;
  strcpy(boot->Magic_Num, "10101010");
  strcpy(boot->Info, "FAT FileOS");
  boot->root = 5;
  boot->Start_Block = myvhard + BlockSize * 5;
  fat *fat1 = (fat *)(myvhard + BlockSize);
  fat *fat2 = (fat *)(myvhard + BlockSize * 3);
  for (int i = 0; i < 6; i++)
  {
    fat1[i].ID = END;
    fat2[i].ID = END;
  }
  for (int i = 6; i < 1000; i++)
  {
    fat1[i].ID = Free;
    fat2[i].ID = Free;
  }

  //第五个磁盘块为启动区
  fcb *root = (fcb *)(myvhard + BlockSize * 5);
  strcpy(root->File_Name, ".");
  strcpy(root->EX_Name, "di");
  root->Attribute = 0; //文件夹

  //设置时间
  time_t rawtime = time(NULL);
  struct tm *time = localtime(&rawtime);
  root->time = time->tm_hour * 2048 + time->tm_min * 32 + time->tm_sec / 2;
  root->date = (time->tm_year - 100) * 512 + (time->tm_mon + 1) * 32 + time->tm_mday;
  root->First_Block = 5;
  root->Is_Free = 1;
  root->Length = 2 * sizeof(fcb);

  fcb *root2 = root + 1;
  memcpy(root2, root, sizeof(fcb));
  strcpy(root2->File_Name, "..");

  for (int i = 0; i < (int)(BlockSize / sizeof(fcb)); i++)
  {
    root2++;
    strcpy(root2->File_Name, "");
    root2->Is_Free = 0;
  }

  FILE *fp = fopen(filename, "w");
  fwrite(myvhard, OS_Size, 1, fp);
  fclose(fp);
  printf("Finished Format the File_System!\n");
}

void List() //展示当前文件夹下的文件信息
{

  //判断是否为目录文件
  if (opfilelist[currfd].Attribute == 1)
  {
    printf("This is a standard file!\n");
    return;
  }

  char buf[Max_Text_Size];
  int i;
  opfilelist[currfd].Cont = 0;
  Sub_Read(currfd, opfilelist[currfd].Length, buf);

  //遍历当前目录的fcb
  fcb *fcbptr = (fcb *)buf;
  for (i = 0; i < (int)(opfilelist[currfd].Length / sizeof(fcb)); i++, fcbptr++)
  {
    if (fcbptr->Is_Free == 1)
    {
      if (fcbptr->Attribute == 0) //文件夹
        printf("<folder>%-8s\t%d%d%d %d:%d\n", fcbptr->File_Name, (fcbptr->date >> 9) + 2000, (fcbptr->date >> 5) & 0x000f, (fcbptr->date) & 0x001f, (fcbptr->time >> 11), (fcbptr->time >> 5) & 0x003f);
      else //文件
        printf("<file>%-8s\t%d%d%d %d:%d\t%d\n", fcbptr->File_Name, (fcbptr->date >> 9) + 2000, (fcbptr->date >> 5) & 0x000f, (fcbptr->date) & 0x001f, (fcbptr->time >> 11), (fcbptr->time >> 5) & 0x003f, fcbptr->Length);
    }
  }
}

void Mkdir(char *dirname) //创建文件夹
{
  char text[Max_Text_Size];
  int i = 0;
  char *fname = strtok(dirname, "."); //按.分割字符串函数
  char *exname = strtok(NULL, ".");
  if (exname != NULL)
  {
    printf("ERROR 183!\n");
    return;
  }

  //读取父目录信息
  opfilelist[currfd].Cont = 0;
  int filelen = Sub_Read(currfd, opfilelist[currfd].Length, text);
  fcb *fcbptr = (fcb *)text;

  //查找是否重名
  for (i = 0; i < (int)(filelen / sizeof(fcb)); i++)
  {
    if (strcmp(dirname, fcbptr[i].File_Name) == 0 && fcbptr->Attribute == 0)
    {
      printf("Error:Folder already exist!\n");
      return;
    }
  }

  //申请一个打开目录项表
  int fd = Get_Free_openfilelist();
  if (fd == -1)
  {
    printf("Openfilelist has been full!\n");
    return;
  }

  //申请一个磁盘块
  unsigned short int block_num = Get_Free_Block();
  if (block_num == END)
  {
    printf("File_System has been full!\n");
    opfilelist[fd].TopenFile = 0;
    return;
  }

  //更新FAT表
  fat *fat1 = (fat *)(myvhard + BlockSize);
  fat *fat2 = (fat *)(myvhard + BlockSize * 3);
  fat1[block_num].ID = END;
  fat2[block_num].ID = END;

  //在父目录中找一个空的fcb,分配给该目录

  for (i = 0; i < (int)(filelen / sizeof(fcb)); i++)
    if (fcbptr->Is_Free == 0)
    {
      break;
    }

  opfilelist[currfd].Cont = i * sizeof(fcb);
  opfilelist[currfd].FcbState = 1;

  //初始化fcb
  fcb *fcbtmp = (fcb *)malloc(sizeof(fcb));
  fcbtmp->Attribute = 0;

  //设置时间
  time_t rawtime = time(NULL);
  struct tm *time = localtime(&rawtime);
  fcbtmp->time = time->tm_hour * 2048 + time->tm_min * 32 + time->tm_sec / 2;
  fcbtmp->date = (time->tm_year - 100) * 512 + (time->tm_mon + 1) * 32 + time->tm_mday;
  strcpy(fcbtmp->File_Name, dirname);
  strcpy(fcbtmp->EX_Name, "di");
  fcbtmp->First_Block = block_num;
  fcbtmp->Length = 2 * sizeof(fcb);
  fcbtmp->Is_Free = 1;
  Sub_Write(currfd, (char *)fcbtmp, sizeof(fcb), 2);

  //设置打开文件表项
  opfilelist[fd].Attribute = 0;
  opfilelist[fd].Cont = 0;
  opfilelist[fd].date = fcbtmp->date;
  opfilelist[fd].time = fcbtmp->time;
  opfilelist[fd].Dir_Num = opfilelist[currfd].First_Block;
  opfilelist[fd].Diroff = i;
  strcpy(opfilelist[fd].File_Name, dirname);
  strcpy(opfilelist[fd].EX_Name, "di");
  opfilelist[fd].FcbState = 0;
  opfilelist[fd].First_Block = fcbtmp->First_Block;
  opfilelist[fd].Is_Free = fcbtmp->Is_Free;
  opfilelist[fd].Length = fcbtmp->Length;
  opfilelist[fd].TopenFile = 1;
  strcat(strcat(strcpy(opfilelist[fd].Dir, (char *)(opfilelist[currfd].Dir)), dirname), "/");

  //设置.和..目录
  fcbtmp->Attribute = 0;
  fcbtmp->date = fcbtmp->date;
  fcbtmp->time = fcbtmp->time;
  strcpy(fcbtmp->File_Name, ".");
  strcpy(fcbtmp->EX_Name, "di");
  fcbtmp->First_Block = block_num;
  fcbtmp->Length = 2 * sizeof(fcb);
  Sub_Write(fd, (char *)fcbtmp, sizeof(fcb), 2);

  fcb *fcbtmp2 = (fcb *)malloc(sizeof(fcb));
  memcpy(fcbtmp2, fcbtmp, sizeof(fcb));
  strcpy(fcbtmp2->File_Name, "..");
  fcbtmp2->First_Block = opfilelist[currfd].First_Block;
  fcbtmp2->Length = opfilelist[currfd].Length;
  fcbtmp2->date = opfilelist[currfd].date;
  fcbtmp2->time = opfilelist[currfd].time;
  Sub_Write(fd, (char *)fcbtmp2, sizeof(fcb), 2);

  //关闭目录的打开文件表项，close会修改父目录中对应目录的fcb信息
  //单个目录存在该目录下的目录文件与父目录下的fcb文件两个
  Close(fd);
  free(fcbtmp);
  free(fcbtmp2);

  //修改父目录的fcb
  fcbptr = (fcb *)text;
  fcbptr->Length = opfilelist[currfd].Length;
  opfilelist[currfd].Cont = 0;
  Sub_Write(currfd, (char *)fcbptr, sizeof(fcb), 2);
  opfilelist[currfd].FcbState = 1;
}

void Rmdir(char *dirname)
{
  int tag = 0;
  int i;
  char buf[Max_Text_Size];
  if (strcmp(dirname, ".") == 0 || strcmp(dirname, "..") == 0)
  {
    printf("You can't remove the root folder!\n");
    return;
  }
  opfilelist[currfd].Cont = 0;
  Sub_Read(currfd, opfilelist[currfd].Length, buf);

  //查找要删除的目录
  fcb *fcbptr = (fcb *)buf;
  for (i = 0; i < (int)(opfilelist[currfd].Length / sizeof(fcb)); i++, fcbptr++)
  {
    if (fcbptr->Is_Free == 0)
      continue;
    if (strcmp(fcbptr->File_Name, dirname) == 0 && fcbptr->Attribute == 0)
    {
      tag = 1;
      break;
    }
  }

  if (tag != 1)
  {
    printf("Folder doesn't exist!\n");
    return;
  }

  /*
  递归遍历删除
  opfilelist[currfd].Cont = 0;
  Sub_Read(currfd, opfilelist[currfd].Length, buf);

  //遍历当前目录的fcb
 
  for (i = 0; i < (int)(opfilelist[currfd].Length / sizeof(fcb)); i++, fcbptr++)
  {
    if (fcbptr->Is_Free == 1)
    {
      if (fcbptr->Attribute == 0) //文件夹
        Rmdir(fcbptr->File_Name);
      else //文件
        Remove(fcbptr->File_Name);
    }
  }
  */

  //更新FAT表
  int block_num = fcbptr->First_Block;
  int nxt_num = 0;
  fat *fat1 = (fat *)(myvhard + BlockSize);
  while (1)
  {
    nxt_num = fat1[block_num].ID;
    fat1[block_num].ID = Free;
    if (nxt_num != END)
      block_num = nxt_num;
    else
      break;
  }

  fat1 = (fat *)(myvhard + BlockSize);
  fat *fat2 = (fat *)(myvhard + BlockSize * 3);
  memcpy(fat2, fat1, BlockSize * 2);

  //更新fcb
  fcbptr->date = 0;
  fcbptr->time = 0;
  fcbptr->EX_Name[0] = '\0';
  fcbptr->File_Name[0] = '\0';
  fcbptr->First_Block = 0;
  fcbptr->Is_Free = 0;
  fcbptr->Length = 0;

  opfilelist[currfd].Cont = i * sizeof(fcb);
  Sub_Write(currfd, (char *)fcbptr, sizeof(fcb), 2);

  //删除目录时应删除相应的fcb，即修改父目录的fcb
  int lognum = i;
  if ((lognum + 1) * sizeof(fcb) == opfilelist[currfd].Length)
  {
    opfilelist[currfd].Length -= sizeof(fcb);
    lognum--;
    fcbptr = (fcb *)buf + lognum;
    while (fcbptr->Is_Free == 0)
    {
      fcbptr--;
      opfilelist[currfd].Length -= sizeof(fcb);
    }
  }

  //更新父目录的fcb
  fcbptr = (fcb *)buf;
  fcbptr->Length = opfilelist[currfd].Length;
  opfilelist[currfd].Cont = 0;
  Sub_Write(currfd, (char *)fcbptr, sizeof(fcb), 2);
  opfilelist[currfd].FcbState = 1;
}

int Create(char *filename)
{
  //判断位置信息
  if (strcmp(filename, "") == 0)
  {
    printf("Please input the filename!\n");
    return -1;
  }
  if (opfilelist[currfd].Attribute == 1)
  {
    printf("You are now in a file.Please close it first if you want to create another!\n");
    return -1;
  }

  opfilelist[currfd].Cont = 0;
  char buf[Max_Text_Size];
  Sub_Read(currfd, opfilelist[currfd].Length, buf);

  int i;
  fcb *fcbptr = (fcb *)buf;
  //重名文件
  for (i = 0; i < (int)(opfilelist[currfd].Length / sizeof(fcb)); i++, fcbptr++)
  {
    if (fcbptr->Is_Free == 0)
      continue;
    if (strcmp(fcbptr->File_Name, filename) == 0 && fcbptr->Attribute == 1)
    {
      printf("The file already exists!\n");
      return -1;
    }
  }

  //申请空白fcb
  fcbptr = (fcb *)buf;
  for (i = 0; i < (int)(opfilelist[currfd].Length / sizeof(fcb)); i++, fcbptr++)
  {
    if (fcbptr->Is_Free == 0)
      break;
  }

  //申请磁盘块，更新FAT表
  int block_num = Get_Free_Block();
  if (block_num == -1)
    return -1;

  fat *fat1 = (fat *)(myvhard + BlockSize);
  fat *fat2 = (fat *)(myvhard + BlockSize * 3);
  fat1[block_num].ID = END;
  memcpy(fat2, fat1, BlockSize * 2);

  //修改fcb信息
  strcpy(fcbptr->File_Name, filename);
  time_t rawtime = time(NULL);
  struct tm *time = localtime(&rawtime);
  fcbptr->time = time->tm_hour * 2048 + time->tm_min * 32 + time->tm_sec / 2;
  fcbptr->date = (time->tm_year - 100) * 512 + (time->tm_mon + 1) * 32 + time->tm_mday;
  fcbptr->First_Block = block_num;
  fcbptr->Is_Free = 1;
  fcbptr->Attribute = 1;
  fcbptr->Length = 0;

  opfilelist[currfd].Cont = i * sizeof(fcb);
  Sub_Write(currfd, (char *)fcbptr, sizeof(fcb), 2);

  //修改父目录fcb
  fcbptr = (fcb *)buf;
  fcbptr->Length = opfilelist[currfd].Length;
  opfilelist[currfd].Cont = 0;
  Sub_Write(currfd, (char *)fcbptr, sizeof(fcb), 2);
  opfilelist[currfd].FcbState = 1;
}

void Remove(char *filename)
{
  char buf[Max_Text_Size];
  opfilelist[currfd].Cont = 0;
  Sub_Read(currfd, opfilelist[currfd].Length, buf);
  int flag = 0;
  int i = 0;
  fcb *fcbptr = (fcb *)buf;
  //查询
  for (i = 0; i < (int)(opfilelist[currfd].Length / sizeof(fcb)); i++, fcbptr++)
  {
    if (strcmp(fcbptr->File_Name, filename) == 0 && fcbptr->Attribute == 1)
    {
      flag = 1;
      break;
    }
  }
  if (flag != 1)
  {
    printf("The folder is not exist!\n");
    return;
  }

  //更新FAT表
  int block_num = fcbptr->First_Block;
  fat *fat1 = (fat *)(myvhard + BlockSize);
  int nxt_num = 0;
  while (1)
  {
    nxt_num = fat1[block_num].ID;
    fat1[block_num].ID = Free;
    if (nxt_num != END)
      block_num = nxt_num;
    else
      break;
  }

  fat1 = (fat *)(myvhard + BlockSize);
  fat *fat2 = (fat *)(myvhard + BlockSize * 3);
  memcpy(fat2, fat1, BlockSize * 2);

  //清空fcb
  fcbptr->date = 0;
  fcbptr->time = 0;
  fcbptr->File_Name[0] = '\0';
  fcbptr->EX_Name[0] = '\0';
  fcbptr->First_Block = 0;
  fcbptr->Is_Free = 0;
  fcbptr->Length = 0;
  opfilelist[currfd].Cont = i * sizeof(fcb);
  Sub_Write(currfd, (char *)fcbptr, sizeof(fcb), 2);

  int lognum = i;
  if ((lognum + 1) * sizeof(fcb) == opfilelist[currfd].Length)
  {
    opfilelist[currfd].Length -= sizeof(fcb);
    lognum--;
    fcbptr = (fcb *)buf + lognum;
    while (fcbptr->Is_Free == 0)
    {
      fcbptr--;
      opfilelist[currfd].Length -= sizeof(fcb);
    }
  }

  //修改父目录.目录文件的fcb
  fcbptr = (fcb *)buf;
  fcbptr->Length = opfilelist[currfd].Length;
  opfilelist[currfd].Cont = 0;
  Sub_Write(currfd, (char *)fcbptr, sizeof(fcb), 2);
  opfilelist[currfd].FcbState = 1;
}

int Open(char *filename)
{
  char buf[Max_Text_Size];
  opfilelist[currfd].Cont = 0;
  Sub_Read(currfd, opfilelist[currfd].Length, buf);
  int flag = 0;
  int i = 0;
  fcb *fcbptr = (fcb *)buf;
  for (i = 0; i < (int)(opfilelist[currfd].Length / sizeof(fcb)); i++, fcbptr++)
  {
    if (strcmp(fcbptr->File_Name, filename) == 0 && fcbptr->Attribute == 1)
    {
      flag = 1;
      break;
    }
  }

  if (flag != 1)
  {
    printf("The file is not exist!\n");
    return -1;
  }

  //申请打开目录并初始化目录
  int fd = Get_Free_openfilelist();
  if (fd == -1)
  {
    printf("Error 563!\n");
    return -1;
  }

  opfilelist[fd].Attribute = 1;
  opfilelist[fd].Cont = 0;
  opfilelist[fd].date = fcbptr->date;
  opfilelist[fd].time = fcbptr->time;
  opfilelist[fd].Length = fcbptr->Length;
  opfilelist[fd].First_Block = fcbptr->First_Block;
  opfilelist[fd].Is_Free = 1;
  strcpy(opfilelist[fd].File_Name, fcbptr->File_Name);
  strcat(strcpy(opfilelist[fd].Dir, (char *)(opfilelist[currfd].Dir)), filename);
  opfilelist[fd].Dir_Num = opfilelist[currfd].First_Block;
  opfilelist[fd].Diroff = i;
  opfilelist[fd].TopenFile = 1;

  opfilelist[fd].FcbState = 0;
  currfd = fd;
  return 1;
}

void CD(char *dirname)
{
  int i = 0;
  int tag = -1;
  int fd;
  if (opfilelist[currfd].Attribute == 1)
  {
    printf("You are now in a file,Please close it first!\n");
    return;
  }
  char *buf = (char *)malloc(CD_Temp_Size);
  opfilelist[currfd].Cont = 0;
  Sub_Read(currfd, opfilelist[currfd].Length, buf);

  fcb *fcbptr = (fcb *)buf;

  //查找目标fcb
  for (i = 0; i < (int)(opfilelist[currfd].Length / sizeof(fcb)); i++, fcbptr++)
  {
    if (strcmp(fcbptr->File_Name, dirname) == 0 && fcbptr->Attribute == 0)
    {
      tag = 1;
      break;
    }
  }

  if (tag != 1)
  {
    printf("Folder doesn't Exist!\n");
    return;
  }
  else
  {
    if (strcmp(fcbptr->File_Name, ".") == 0)
    {
      return;
    }
    else if (strcmp(fcbptr->File_Name, "..") == 0)
    {
      if (currfd == 0)
        return;
      else
      {
        currfd = Close(currfd);
        return;
      }
    }
    else
    {
      fd = Get_Free_openfilelist();
      if (fd == -1)
        return;
      opfilelist[fd].Attribute = fcbptr->Attribute;
      opfilelist[fd].Cont = 0;
      opfilelist[fd].date = fcbptr->date;
      opfilelist[fd].time = fcbptr->time;
      strcpy(opfilelist[fd].File_Name, fcbptr->File_Name);
      strcpy(opfilelist[fd].EX_Name, fcbptr->EX_Name);
      opfilelist[fd].First_Block = fcbptr->First_Block;
      opfilelist[fd].Is_Free = fcbptr->Is_Free;

      opfilelist[fd].FcbState = 0;
      opfilelist[fd].Length = fcbptr->Length;
      strcat(strcat(strcpy(opfilelist[fd].Dir, (char *)(opfilelist[currfd].Dir)), dirname), "/");

      opfilelist[fd].Dir_Num = opfilelist[currfd].First_Block;
      opfilelist[fd].Diroff = i;
      opfilelist[fd].TopenFile = 1;
      currfd = fd;
    }
  }
}

int Close(int fd)
{
  if (fd > Max_File_Open || fd < 0)
  {
    printf("Failed to close the file!\n");
    return -1;
  }

  int i = 0;
  char buf[Max_Text_Size];
  int father_fd = -1;
  fcb *fcbptr;
  for (i = 0; i < Max_File_Open; i++)
  {
    if (opfilelist[i].First_Block == opfilelist[fd].Dir_Num)
    {
      father_fd = i;
      break;
    }
  }

  if (father_fd == -1)
  {
    printf("error 681当前文件不存在父目录\n");
    return -1;
  }

  if (opfilelist[fd].FcbState == 1)
  {
    Sub_Read(father_fd, opfilelist[father_fd].Length, buf);

    //更新fcb
    fcbptr = (fcb *)(buf + sizeof(fcb) * opfilelist[fd].Diroff);
    strcpy(fcbptr->EX_Name, opfilelist[fd].EX_Name);
    strcpy(fcbptr->File_Name, opfilelist[fd].File_Name);
    fcbptr->First_Block = opfilelist[fd].First_Block;
    fcbptr->Is_Free = opfilelist[fd].Is_Free;
    fcbptr->Length = opfilelist[fd].Length;
    fcbptr->date = opfilelist[fd].date;
    fcbptr->time = opfilelist[fd].time;
    fcbptr->Attribute = opfilelist[fd].Attribute;
    opfilelist[father_fd].Cont = opfilelist[fd].Diroff * sizeof(fcb);
    Sub_Write(father_fd, (char *)fcbptr, sizeof(fcb), 2);
  }

  //释放打开文件表
  memset(&opfilelist[fd], 0, sizeof(user_open));
  currfd = father_fd;
  return father_fd;
}

int Read(int fd)
{
  if (fd < 0 || fd >= Max_File_Open)
  {
    printf("File doesn't exist!\n");
    return -1;
  }

  opfilelist[fd].Cont = 0;
  char text[Max_Text_Size] = "\0";
  Sub_Read(fd, opfilelist[fd].Length, text);
  printf("--------------------------------File content-------------------------------\n");
  printf("%s\n", text);
  printf("---------------------------------------------------------------------------\n");
  return 1;
}

int Write(int fd)
{
  if (fd < 0 || fd >= Max_File_Open)
  {
    printf("Error 730!\n");
    return -1;
  }
  int write_style;
  /*while (1)
  {
    printf("Choose the model to write:\n");
    printf("1:Rewrite the file\n2:Covering write\n3:Continuation\n");
    scanf("%d", &write_style);
    if (write_style < 1 || write_style > 3)
      printf("Error Parameter!\n");
    else
      break;
  }*/
  write_style = 1;

  char text[Max_Text_Size] = "\0";
  char texttmp[Max_Text_Size] = "\0";
  printf("---------------------Write the file,End with new line and '--EOF'-----------------------\n");
  getchar();
  while (gets(texttmp))
  {
    if (strcmp(texttmp, "--EOF") == 0)
      break;
    texttmp[strlen(texttmp)] = '\n';
    strcat(text, texttmp);
  }
  printf("------------------------------------------------------------------------\n");

  text[strlen(text)] = '\0';
  Sub_Write(fd, text, strlen(text) + 1, write_style);
  opfilelist[fd].FcbState = 1;
  return 1;
}

int Sub_Read(int fd, int len, char *text)
{
  int len_tmp = len;
  char *textptr = text;
  unsigned char *buf = (unsigned char *)malloc(1024);
  if (buf == NULL)
  {
    printf("Error 771!\n");
    return -1;
  }

  int off = opfilelist[fd].Cont;
  int block_num = opfilelist[fd].First_Block;
  fat *fatptr = (fat *)(myvhard + BlockSize) + block_num;

  //定位读取目标盘块和块内地址
  while (off >= BlockSize)
  {
    off -= BlockSize;
    block_num = fatptr->ID;
    if (block_num == END)
    {
      printf("Data Block doesn't exist!\n");
      return -1;
    }

    fatptr = (fat *)(myvhard + BlockSize) + block_num;
  }

  unsigned char *blockptr = myvhard + BlockSize * block_num;
  memcpy(buf, blockptr, BlockSize);

  //读取内容
  while (len > 0)
  {
    if (BlockSize - off > len)
    {
      memcpy(textptr, buf + off, len);
      textptr += len;
      off += len;
      opfilelist[fd].Cont += len;
      len = 0;
    }
    else
    {
      memcpy(textptr, buf + off, BlockSize - off);
      textptr += BlockSize - off;
      len -= BlockSize - off;
      block_num = fatptr->ID;
      if (block_num == END)
      {
        printf("读错误，位于804行\n");
        break;
      }
      fatptr = (fat *)(myvhard + BlockSize) + block_num;
      blockptr = myvhard + BlockSize * block_num;
      memcpy(buf, blockptr, BlockSize);
    }
  }
  free(buf);
  return len_tmp - len;
}

int Sub_Write(int fd, char *text, int len, char write_style)
{
  int block_num = opfilelist[fd].First_Block;
  int i;
  int tmp_num;
  int lentmp = 0;
  char *textptr = text;
  char buf[BlockSize];
  fat *fatptr = (fat *)(myvhard + BlockSize) + block_num;
  unsigned char *blockptr;
  if (write_style == 1)
  {
    opfilelist[fd].Cont = 0;
    opfilelist[fd].Length = 0;
  }
  else if (write_style == 3)
  {
    opfilelist[fd].Cont = opfilelist[fd].Length;
    if (opfilelist[fd].Attribute == 1)
      if (opfilelist[fd].Length != 0)
        opfilelist[fd].Cont = opfilelist[fd].Length - 1;
  }

  int off = opfilelist[fd].Cont;

  //定位磁盘块和块内偏移量
  while (off >= BlockSize)
  {
    block_num = fatptr->ID;
    if (block_num == END)
    {
      printf("写错误847\n");
      return -1;
    }
    fatptr = (fat *)(myvhard + BlockSize) + block_num;
    off -= BlockSize;
  }

  blockptr = (unsigned char *)(myvhard + BlockSize * block_num);

  //写入磁盘
  while (len > lentmp)
  {
    memcpy(buf, blockptr, BlockSize);
    for (; off < BlockSize; off++)
    {
      *(buf + off) = *textptr;
      textptr++;
      lentmp++;
      if (len == lentmp)
        break;
    }

    memcpy(blockptr, buf, BlockSize);

    //一个磁盘块放不下，则申请多一个磁盘块
    if (off == BlockSize && len != lentmp)
    {
      off = 0;
      block_num = fatptr->ID;
      if (block_num == END)
      {
        block_num = Get_Free_Block();
        if (block_num == END)
        {
          printf("Data Block has full!\n");
          return -1;
        }

        blockptr = (unsigned char *)(myvhard + BlockSize * block_num);
        fatptr->ID = block_num;
        fatptr = (fat *)(myvhard + BlockSize) + block_num;
        fatptr->ID = END;
      }
      else
      {
        blockptr = (unsigned char *)(myvhard + BlockSize * block_num);
        fatptr = (fat *)(myvhard + BlockSize) + block_num;
      }
    }
  }

  opfilelist[fd].Cont += len;
  if (opfilelist[fd].Cont > opfilelist[fd].Length)
    opfilelist[fd].Length = opfilelist[fd].Cont;

  //删除多余磁盘块
  if (write_style == 1 || (write_style == 2 && opfilelist[fd].Attribute == 0))
  {
    off = opfilelist[fd].Length;
    fatptr = (fat *)(myvhard + BlockSize) + opfilelist[fd].First_Block;
    while (off >= BlockSize)
    {
      block_num = fatptr->ID;
      off -= BlockSize;
      fatptr = (fat *)(myvhard + BlockSize) + block_num;
    }
    while (1)
    {
      if (fatptr->ID != END)
      {
        i = fatptr->ID;
        fatptr->ID = Free;
        fatptr = (fat *)(myvhard + BlockSize) + i;
      }
      else
      {
        fatptr->ID = Free;
        break;
      }
    }

    fatptr = (fat *)(myvhard + BlockSize) + block_num;
    fatptr->ID = END;
  }

  memcpy((fat *)(myvhard + BlockSize * 3), (fat *)(myvhard + BlockSize), BlockSize * 2);
  return len;
}

int Get_Free_openfilelist()
{
  for (int i = 0; i < Max_File_Open; i++)
  {
    if (opfilelist[i].TopenFile == 0)
    {
      opfilelist[i].TopenFile = 1;
      return i;
    }
  }
  return -1;
}

unsigned short int Get_Free_Block()
{
  fat *fat1 = (fat *)(myvhard + BlockSize);
  for (int i = 0; i < (int)(OS_Size / BlockSize); i++)
  {
    if (fat1[i].ID == Free)
      return i;
  }
  return END;
}

void help()
{
  printf("*************************Here comes the commands***************************\n");
  printf("mkdir----->to make a new folder\nrmdir----->to remove a folder\nls----->to show the content at current list\n");
  printf("cd----->to change the folder\ncreate----->to create a standard file\nopen----->to open a standrad file\n");
  printf("close----->to close a standard file\nread----->to read a standard file\nwrite----->to write a standard file\n");
  printf("delete----->to delete a standard file\nexit----->to quit the File_System\nnew----->to set up a new File_System\n");
  printf("sys----->to open a exist File_System\nhelp----->to open the commands list\n");
  printf("**********You could open the commands list whenever you want***************\n");
}
